package com.bdzl.auth.service.impl;

import com.bdzl.auth.common.exception.BDException;
import com.bdzl.auth.common.utils.*;
import com.bdzl.auth.service.*;
import com.bdzl.pub.common.Tree;
import com.bdzl.pub.entity.sys.*;
import com.bdzl.pub.util.param.R;
import org.apache.shiro.SecurityUtils;
import org.omg.CORBA.INTERNAL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private RoleMeauService roleMeauService;

    /**
     * @Author Zhn
     * @Description //TODO 登录接口
     * @Date 18:17 2021/5/12
     * @Param [sysUser, r]
     * @return com.bdzl.pub.util.param.R
    **/
    @Override
    public R userInfo(UserDO sysUser, R r) {
        String syspassword = sysUser.getUserPwd();
        String username = sysUser.getUserLgname();
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set("user_token_" + token, token);
        redisUtil.expire("user_token_" + token, JwtUtil.EXPIRE_TIME*20);
        //获取用户
        sysUser = userService.getByUserLgname(username);
        Map<String,Object> param = new HashMap<>();
        param.put("userId",sysUser.getUserId());
        //根据用户获取用户角色关系列表
        List<UserRoleDO> list = userRoleService.list(param);
        List<RoleDO> roleDOList = new ArrayList<>();//角色列表
        List<Tree<MeauDO>> PcmeauDOList = new ArrayList<>();//菜单列表
        List<Tree<MeauDO>> AppmeauDOList = new ArrayList<>();//菜单列表
        for (UserRoleDO item:list) {
            //获取角色
            roleDOList.add(roleService.get(item.getRoleId()));
            //根据角色ID获取PC菜单列表
            PcmeauDOList.addAll(roleMeauService.getMeauDOtreeByRoleId(item.getRoleId(),"Pc"));
            //根据角色ID获取APP菜单列表
            AppmeauDOList.addAll(roleMeauService.getMeauDOtreeByRoleId(item.getRoleId(),"APP"));
        }
        //保存最近登录时间
        r.put("token",token); //登录token
        r.put("userInfo",sysUser);//登录用户
        r.put("roleList",roleDOList);//角色列表
        r.put("PcMeauDOList",PcmeauDOList);//pc菜单列表
        r.put("AppMeauDOList",AppmeauDOList);//pc菜单列表
        Date userLastLgtime = sysUser.getUserLastLgtime();
        if (userLastLgtime!=null && !userLastLgtime.equals("")){
            r.put("loginTime", DateUtils.formatTime(sysUser.getUserLastLgtime()));//上次登录时间
        }else {
            r.put("loginTime", DateUtils.formatTime(DateUtils.getDate()));//上次登录时间
        }
        sysUser.setUserLastLgtime(DateUtils.getDate());
        userService.update(sysUser);
        return r;
    }

    /**
     * @Author Zhn
     * @Description //TODO 登录验证接口
     * @Date 18:15 2021/5/12
     * @Param [user]
     * @return com.bdzl.pub.util.param.R
     **/
    @Override
    public R login(UserDO user){
        //1. 校验用户是否有效
        //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug，if条件永远为false
        String username = user.getUserLgname();
        String password = user.getUserPwd();
        UserDO sysUser = userService.getByUserLgname(username);
        R r = userService.checkUserIsEffective(sysUser);
        if(!R.ok().equals(r)) {
            throw new BDException(r.get("respMsg").toString());
        }
        //2. 校验用户名或密码是否正确
        if (user.getUserId()==null){
            password = MD5Utils.encrypt(username, password);
        }
        String syspassword = sysUser.getUserPwd();
        if (!syspassword.equals(password)) {
            throw new BDException("账户名或密码错误！");
        }
        return R.ok();
    }
    /**
     * @Author Zhn
     * @Description //TODO 退出接口
     * @Date 18:25 2021/5/12
     * @Param [request, response]
     * @return com.bdzl.pub.util.param.R
     **/
    @Override
    public R logout(HttpServletRequest request, HttpServletResponse response) {
        //用户退出逻辑
        String token = request.getHeader("X-Access-Token");
        if(oConvertUtils.isEmpty(token)) {
            return R.error("退出登录失败！");
        }
        String username = JwtUtil.getUsername(token);
        UserDO sysUser = userService.getByUserLgname(username);
        if(sysUser!=null) {
            //清空用户登录Token缓存
            redisUtil.del("user_token_" + token);
            //清空用户登录Shiro权限缓存
//            redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
            //清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
//            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
            //调用shiro的logout
            SecurityUtils.getSubject().logout();
            return R.ok("退出登录成功！");
        }else {
            return R.error("Token无效!");
        }
    }

    /**
     * @Author Zhn
     * @Description //TODO 发送短信
     * @Date 17:24 2021/5/22
     * @Param [mobileCodeDO, username, id, phone, time]  发送短信记录， 用户名 ，模板ID 。手机号 ， 时间
     * @return com.bdzl.pub.util.param.R
     **/
    @Override
    public MobileCodeDO getMobileCodeDO(MobileCodeDO mobileCodeDO, String username, String id, String phone,Integer time){
        UserDO byUserLgname = userService.getByUserLgname(username);
        mobileCodeDO.setMcType("验证码");
        mobileCodeDO.setMcCruser(byUserLgname.getUserId());//创建者
        mobileCodeDO.setMcTemplateid(id);//模版编号
        mobileCodeDO.setMcMobile(phone);//手机号码
        Date date = DateUtils.getDate();
        mobileCodeDO.setMcCreTime(date);//创建时间
        if (time==null){
            //把验证码默认10分钟
            mobileCodeDO.setMcValidTime(DateUtils.rollMinute(date,10));
        }else {
            //自定义到期时间
            mobileCodeDO.setMcValidTime(DateUtils.rollMinute(date,time));
        }
        mobileCodeDO.setMcStatus(0);
        if (mobileCodeDO.getMcCode().equals("OFF")){
            mobileCodeDO.setMcStatus(1);
        }
        return mobileCodeDO;
    }
}
